package com.feng.seata.service;

import com.feng.seata.mapper.ProductMapper;
import com.feng.seata.tcc.action.IStockTccAction;
import com.feng.seata.tcc.action.TccActionResultWrap;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;

/**
 * 自定义解决幂等、悬挂和空回滚问题
 * @author yinglong.zhang
 * @description
 * @date 2024-1-30 17:17
 */
public class StockServiceImplBak implements IStockTccAction {

//    @Resource
    private ProductMapper productMapper;

    @Override
    public boolean prepareDeductStock(BusinessActionContext businessActionContext, Long productId, Integer buyNum) {
        // 如果成功，返回 true；如果失败，返回 false
        String xid = businessActionContext.getXid();
        // 幂等性判断
        if (TccActionResultWrap.hasPrepareResult(xid)) {
            return true;
        }
        // 避免空悬挂，已经执行过回滚了就不能再预留资源
        if (TccActionResultWrap.hasRollbackResult(xid) || TccActionResultWrap.hasCommitResult(xid)) {
            return false;
        }
        // 预扣库存
       // 相关sql： update stock_tcc_tbl set count = count - #{count,jdbcType=INTEGER}, pre_deduct_count = pre_deduct_count + #{count,jdbcType=INTEGER} where commodity_code = #{commodityCode,jdbcType=VARCHAR} and count <![CDATA[ >= ]]> #{count,jdbcType=INTEGER}
        boolean result = productMapper.prepareDeductStock(productId, buyNum) > 0;
        // 记录执行结果：xid:result
        // 以便回滚时判断是否是空回滚
        TccActionResultWrap.prepareSuccess(xid);
        return result;
    }

    @Override
    public boolean commitDeductStock(BusinessActionContext businessActionContext) {
        String xid = businessActionContext.getXid();
        // 幂等性判断
        if (TccActionResultWrap.hasCommitResult(xid)) {
            return true;
        }
        Map<String, Object> actionContext = businessActionContext.getActionContext();
        Long productId = (Long) actionContext.get("productId");
        int count = (int) actionContext.get("count");
        // 执行提交操作，扣除预留款
        boolean result = productMapper.commitDeductStock(productId, count) > 0;
        // 清除预留结果
        TccActionResultWrap.removePrepareResult(xid);
        // 设置提交结果
        TccActionResultWrap.commitSuccess(xid);
        return result;
    }

    @Override
    public boolean rollbackDeductStock(BusinessActionContext businessActionContext) {
        String xid = businessActionContext.getXid();
        // 幂等性判断
        if (TccActionResultWrap.hasRollbackResult(xid)) {
            return true;
        }
        // 没有预留资源结果，回滚不做任何处理；
        if (!TccActionResultWrap.hasPrepareResult(xid)) {
            // 设置回滚结果，防止空悬挂
            TccActionResultWrap.rollbackResult(xid);
            return true;
        }
        // 执行回滚
        Map<String, Object> actionContext = businessActionContext.getActionContext();
        Long productId = (Long) actionContext.get("productId");
        int count = (int) actionContext.get("count");
        boolean result = productMapper.rollbackDeductStock(productId, count) > 0;
        // 清除预留结果
        TccActionResultWrap.removePrepareResult(xid);
        // 设置回滚结果
        TccActionResultWrap.rollbackResult(xid);
        return result;
    }
}
